
use quote::quote;
use syn::{parse::Parse, Attribute, DataStruct, Ident};
use crate::utils;
use crate::attr::ResponseAttr;

pub fn derive_responder(_data_enum: DataStruct, struct_name: Ident, attrs: Vec<Attribute>) -> proc_macro2::TokenStream {
    let aqua = utils::get_aqua_path();

    // Default
    let mut status_code = 200u16;
    let mut content_type = quote! { #aqua::http::HttpContentType::ApplicationJson };

    // only handle #[response(...)]
    for attr in attrs.iter()
        .filter(|a| a.path().is_ident("response"))
    {
        // parse key-value pair in #[response(...)], like (status = 500, content_type = "json")
        let Ok(parsed) = attr.parse_args_with(ResponseAttr::parse) else {
            continue;
        };

        // parsed.entries like a list, each element is a key-value pair
        if let Err(e) = parsed.extract_filed(&mut status_code, &mut content_type) {
            return e;
        }
    }

    let expanded = quote! {
        impl #aqua::convert::IntoResponse for #struct_name {
            fn status_code(&self) -> u16 {
                #status_code
            }

            fn content_type(&self) -> #aqua::http::HttpContentType {
                #content_type
            }

            fn into_body(self) -> Vec<u8> {
                serde_json::to_vec(&self).expect("failed to serialize response")
            }
        }
    };

    expanded.into()
}